package ca.scotthyndman.as2haxe.dom;

import java.util.ArrayList;
import java.util.List;

import ca.scotthyndman.as2haxe.dom.visitor.IVisitor;

/**
 * Represents an if statement.
 */
public class ASIfStatement extends ASStatement {

	/**
	 * The "expression" structural property of this node type.
	 * 
	 * @since 3.0
	 */
	public static final ASChildPropertyDescriptor EXPRESSION_PROPERTY = new ASChildPropertyDescriptor(
			ASIfStatement.class, "expression", ASExpression.class, true);

	/**
	 * The "thenStatement" structural property of this node type.
	 * 
	 * @since 3.0
	 */
	public static final ASChildPropertyDescriptor THEN_STATEMENT_PROPERTY = new ASChildPropertyDescriptor(
			ASIfStatement.class, "thenStatement", ASStatement.class, true);

	/**
	 * The "elseStatement" structural property of this node type.
	 * 
	 * @since 3.0
	 */
	public static final ASChildPropertyDescriptor ELSE_STATEMENT_PROPERTY = new ASChildPropertyDescriptor(
			ASIfStatement.class, "elseStatement", ASStatement.class, false);

	/**
	 * A list of property descriptors (element type:
	 * {@link ASPropertyDescriptor}), or null if uninitialized.
	 */
	private static final List<ASPropertyDescriptor> PROPERTY_DESCRIPTORS;

	static {
		List<Object> properyList = new ArrayList<Object>(4);
		createPropertyList(ASIfStatement.class, properyList);
		addProperty(EXPRESSION_PROPERTY, properyList);
		addProperty(THEN_STATEMENT_PROPERTY, properyList);
		addProperty(ELSE_STATEMENT_PROPERTY, properyList);
		PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
	}

	/**
	 * Returns a list of structural property descriptors for this node type.
	 * Clients must not modify the result.
	 * 
	 * @return a list of property descriptors
	 */
	public static List<ASPropertyDescriptor> propertyDescriptors() {
		return PROPERTY_DESCRIPTORS;
	}

	ASExpression expression;

	ASStatement thenStatement;

	ASStatement elseStatement;

	/**
	 * Constructs a new instance of ASIfStatement
	 * 
	 * @param ast
	 *            The abstract syntax tree that owns this element
	 */
	public ASIfStatement(AST ast) {
		super(ast);
	}

	public ASExpression getExpression() {
		return expression;
	}

	public void setExpression(ASExpression expression) {
		if (expression == null) {
			throw new IllegalArgumentException();
		}
		ASTNode oldChild = this.expression;
		preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
		this.expression = expression;
		postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
	}

	public ASStatement getThenStatement() {
		return thenStatement;
	}

	public void setThenStatement(ASStatement thenStatement) {
		if (thenStatement == null) {
			throw new IllegalArgumentException();
		}
		ASTNode oldChild = this.thenStatement;
		preReplaceChild(oldChild, thenStatement, THEN_STATEMENT_PROPERTY);
		this.thenStatement = thenStatement;
		postReplaceChild(oldChild, thenStatement, THEN_STATEMENT_PROPERTY);
	}

	public ASStatement getElseStatement() {
		return elseStatement;
	}

	public void setElseStatement(ASStatement elseStatement) {
		ASTNode oldChild = this.elseStatement;
		preReplaceChild(oldChild, elseStatement, ELSE_STATEMENT_PROPERTY);
		this.elseStatement = elseStatement;
		postReplaceChild(oldChild, elseStatement, ELSE_STATEMENT_PROPERTY);
	}

	//
	// ======== INTERNAL GET SET
	//

	/*
	 * (omit javadoc for this method) Method declared on ASTNode.
	 */
	final ASTNode internalGetSetChildProperty(
			ASChildPropertyDescriptor property, boolean get, ASTNode child) {
		if (property == EXPRESSION_PROPERTY) {
			if (get) {
				return getExpression();
			} else {
				setExpression((ASExpression) child);
				return null;
			}
		}
		if (property == THEN_STATEMENT_PROPERTY) {
			if (get) {
				return getThenStatement();
			} else {
				setThenStatement((ASStatement) child);
				return null;
			}
		}
		if (property == ELSE_STATEMENT_PROPERTY) {
			if (get) {
				return getElseStatement();
			} else {
				setElseStatement((ASStatement) child);
				return null;
			}
		}
		// allow default implementation to flag the error
		return super.internalGetSetChildProperty(property, get, child);
	}

	// ===== TO STRING AND VISITOR

	@Override
	public String toString() {
		StringBuffer buf = new StringBuffer();
		buf.append("if (");

		buf.append(getExpression().toString()).append(")\n ");
		buf.append(getThenStatement().toString()).append("\n");
		if (getElseStatement() != null) {
			buf.append("else\n");
			buf.append(getElseStatement().toString());
		}

		return buf.toString();
	}

	@Override
	public void accept(IVisitor as2Visitor, boolean visitChilds) {
		visitChilds = as2Visitor.visit(this);

		if (!visitChilds) {
			return;
		}

		getExpression().accept(as2Visitor, visitChilds);
		getThenStatement().accept(as2Visitor, visitChilds);
		if (getElseStatement() != null) {
			getElseStatement().accept(as2Visitor, visitChilds);
		}
	}
}
